#include "../include/TypeChecker.h"

void TypeChecker::visit(parameter *) {
    for (int i = 0; i < gvNum; i++) {
        if (strcmp(gv[i].name, node->strValue) == 0)
            return;
    }
    for (int i = 0; i < fNum; i++) {
        if (strcmp(func[i].name, node->strValue) == 0)
            return;
    }
    for (int i = 0; i < lvNum; i++) {
        if (strcmp(lv[i].name, node->strValue) == 0)
            return;
    }
    if (strcmp(node->strValue, "scanf") == 0 || strcmp(node->strValue, "printf") == 0)
        return;
    cerr << "Use of undeclared identifier '" << node->strValue << "'";
    exit(1);
}

void TypeChecker::visit(FuncDef *) {
    whichFunc = node->left->left->next->strValue;
}

void TypeChecker::visit(Return_Stmt *) {
    if (strcmp(node->left->nodeType, "parameter") == 0) {
        for (int i = 0; i < gvNum; i++) {
            if (strcmp(gv[i].name, node->left->strValue) == 0) {
                for (int j = 0; j < fNum; j++) {
                    if (strcmp(func[j].name, whichFunc) == 0) {
                        if (strcmp(gv[i].typeGLF, func[j].typeGLF) == 0)
                            return;
                    }
                }
            }
        }
        for (int i = 0; i < lvNum; i++) {
            if (strcmp(lv[i].name, node->left->strValue) == 0) {
                for (int j = 0; j < fNum; j++) {
                    if (strcmp(func[j].name, whichFunc) == 0) {
                        if (strcmp(lv[i].typeGLF, func[j].typeGLF) == 0)
                            return;
                    }
                }
            }
        }
    } else {
        for (int j = 0; j < fNum; j++) {
            if (strcmp(func[j].name, whichFunc) == 0) {
                if (strcmp("int", func[j].typeGLF) == 0)
                    return;
            }
        }
    }
    cerr << "Void function '" << whichFunc << "' should not return a value";
    exit(4);
}

void TypeChecker::checkMain() {
    for (int i = 0; i < fNum; i++) {
        if (strcmp(func[i].name, "main") == 0)
            return;
    }
    cerr << "undefined reference to `main'";
    exit(6);
}
